
#include <BFile>
#include <BOpenGL>
#include <BKeyEvent>
#include <BMouseEvent>
#include <BStyleDocument>
#include <BLabelItem>

#include "IGlobal.h"
#include "member_BLabelItem.h"
#include "member_BGraphicWidget.h"
#include "member_BStyle.h"
#include "member_BObject.h"

using namespace BWE;

#define member					(*(member_BLabelItem*)_ptr)
#define member_allocate()		_ptr = new member_BLabelItem(this)
#define member_release()		delete (member_BLabelItem*)_ptr

BLabelItem::BLabelItem(BGraphicItem* parent) : BGraphicItem(parent)
{
	member_allocate();
}
BLabelItem::BLabelItem(const BString& text, BGraphicItem* parent) : BGraphicItem(parent)
{
	member_allocate();
	member.text = text;
}
BLabelItem::BLabelItem(BWidget* widget, BGraphicItem* parent) : BGraphicItem(widget, parent)
{
	member_allocate();
}
BLabelItem::BLabelItem(BWidget* widget, const BString& text, BGraphicItem* parent) : BGraphicItem(widget, parent)
{
	member_allocate();
	member.text = text;
}
BLabelItem::BLabelItem(Graph graph, const BString& text, Form form)
{
	member_allocate();
	member.graph = graph;
	member.text = text;
	member.alignment.ia_form = form;
}
BLabelItem::BLabelItem(BImage* image, const BString& text, Form form)
{
	member_allocate();
	member.image = image;
	member.text = text;
	member.alignment.ia_form = form;
}
BLabelItem::~BLabelItem()
{
	member_release();
}

bool BLabelItem::setAlign(Align align)
{
	if (member.alignment.ia_align != align)
	{
		member.alignment.ia_align = align;
		this->emit(Signal_AlignChanged, align);
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
Align BLabelItem::align() const
{
	return member.alignment.ia_align;
}

bool BLabelItem::setForm(Form form)
{
	if (member.alignment.ia_form != form)
	{
		member.alignment.ia_form = form;
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
Form BLabelItem::form() const
{
	return member.alignment.ia_form;
}

bool BLabelItem::setGraph(Graph graph)
{
	if (member.graph != graph)
	{
		member.graph = graph;
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
Graph BLabelItem::graph() const
{
	return member.graph;
}

bool BLabelItem::setImageSize(int imageWidth, int imageHeight)
{
	return setImageSize(BSize(imageWidth, imageHeight));
}
bool BLabelItem::setImageSize(const BSize& imageSize)
{
	if (member.imageSize != imageSize)
	{
		member.imageSize = imageSize;
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
const BSize& BLabelItem::imageSize() const
{
	return member.imageSize;
}

bool BLabelItem::setText(const BString& text)
{
	if (member.text != text)
	{
		member.text = text;
		this->fresh();
		emit(Signal_TextChanged, member.text);
		return true;
	}
	return false;
}
const BString& BLabelItem::text() const
{
	return member.text;
}

bool BLabelItem::setImage(BImage* image)
{
	if (member.image != image)
	{
		member.image = image;
		this->fresh();
		emit(Signal_ImageChanged, member.image);
		return true;
	}
	return false;
}
BImage* BLabelItem::image()
{
	return member.image;
}
const BImage* BLabelItem::image() const
{
	return member.image;
}

bool BLabelItem::setColor(BByte r, BByte g, BByte b, BByte a)
{
	return setColor(BColor(r, g, b, a));
}
bool BLabelItem::setColor(const BColor& color)
{
	if (member.color != color)
	{
		member.color = color;
		this->fresh();
		return true;
	}
	return false;
}
const BColor& BLabelItem::color() const
{
	return member.color;
}

bool BLabelItem::query(const BString& text, BValue& value) const
{
	return BObject::query(text, value);
}

void BLabelItem::paint(BPainter& painter)
{
	drawBackground(painter);
	drawForeground(painter);

	State state = painter.state();
	if (this->hovered())
		state |= State_Hovered;
	else if (this->selected())
		state |= State_Selected;

	BImage* image = member.image;
	if (image)
	{
		BRect imageRect = member.alignment.ia_iconRect;
		painter.setColor(member.color);
		painter.drawImage(imageRect, image);
	}
	else
	{
		if (Graph graph = member.graph)
		{
			BRect imageRect = member.alignment.ia_iconRect;
			if (painter.setColor(member.color))
				painter.drawGraph(imageRect, graph);
		}
	}
	if (painter.setColor(Color_Text, state))
	{
		BRect textRect = member.alignment.ia_textRect;
		member.block.paint(painter);
	}

	drawMargin(painter);
	drawBorder(painter);
 }

void BLabelItem::resizeEvent(const BEvent& event)
{
	member.dirty = true;
	BGraphicItem::resizeEvent(event);
}

void BLabelItem::styleEvent(const BEvent& event)
{
	BGraphicItem::styleEvent(event);

	const BStyle* style = event.value();

	const BValue& alignValue = style->value(Value_Align);
	if (alignValue.valid())
		member.alignment.ia_align = alignValue;

	const BValue& formValue = style->value(Value_Form);
	if (formValue.valid())
		member.alignment.ia_form = formValue;

	const BValue& textValue = style->value(Value_Text);
	if (textValue.valid())
		member.text = (const BString&)textValue;

	const BValue& colorValue = style->value(Value_Color);
	if (colorValue.valid())
		member.color = colorValue;

	const BValue& graphValue = style->value(Value_Graph);
	if (graphValue.valid())
		member.graph = graphValue;

	const BValue& imageValue = style->value(Value_Image);
	if (imageValue.valid())
		member.image = (BImage*)imageValue;

	const BValue& iconSizeValue = style->value(Value_Image_Size);
	if (iconSizeValue.valid())
		member.imageSize = iconSizeValue;

}
void BLabelItem::freshEvent(const BEvent& event)
{
	BGraphicItem::freshEvent(event);
	if (member.dirty)
	{
		member.adjustRects(this->font());
		member.dirty = false;
	}
}
